package com.koicarp.agent.common.tools;

import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;

/**
 * @ClassName:  StreamUtil   
 * @Description: 流式工具类
 * @author: liutao
 * @date:   2024年7月31日 下午2:15:03    
 * @Copyright:  
 */
public class StreamUtil {

	private StreamUtil() {
		
	}
	
	/**
	 * 
	 * @Description:     将collection过滤
	 * @param <E>
	 * @param collection 需要过滤的集合
	 * @param function   过滤方法
	 * @return List<E>   过滤后的list
	 *
	 */
	public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) {
		if (CollUtil.isEmpty(collection)) {
			return CollUtil.newArrayList();
		}
		
		return collection.stream().filter(function).collect(Collectors.toList());
	}
	
	/**
	 * 
	 * @Description:     找到流中满足条件的第一个元素
	 * @param collection 需要过滤的集合
	 * @param function   过滤方法
	 * @return E         找到符号条件的第一个元素，没知道返回null
	 * @throws：异常描述
	 *
	 */
	public static <E> E findFirst(Collection<E> collection, Predicate<E> function) {
		if (CollUtil.isEmpty(collection)) {
			return null;
		}
		
		return collection.stream().filter(function).findFirst().orElse(null);
	}
	
	/**
	 * 
	 * @Description:       找到流中任意一个满足条件的元素
     * @param collection   需要查询的集合
     * @param function     过滤方法
	 * @return Optional<E> 找到符合条件的任意一个元素，没有则返回null
	 * @throws：异常描述
	 *
	 */
	public static <E> Optional<E> findAny(Collection<E> collection, Predicate<E> function) {
        if (CollUtil.isEmpty(collection)) {
            return Optional.empty();
        }
        return collection.stream().filter(function).findAny();
	}
	
	/**
	 * 
	 * @Description:     将collection 拼接
	 * @param collection 需要转换的集合
	 * @param function   拼接方法
	 * @param delimiter  拼接符
	 * @return String 
	 * @throws：异常描述
	 *
	 */
	public static <E> String join(Collection<E> collection, Function<E, String> function,
			CharSequence delimiter) {
        if (CollUtil.isEmpty(collection)) {
            return StrUtil.EMPTY;
        }
        return collection.stream().map(function)
        		.filter(Objects::nonNull).collect(Collectors.joining(delimiter));
	}
	
	/**
	 * 
	 * @Description:     collection排序
	 * @param collection 需要转换的集合
	 * @param comparing  排序方法
	 * @return List<E>
	 * @throws：异常描述
	 *
	 */
	public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) {
		if (CollUtil.isEmpty(collection)) {
			return CollUtil.newArrayList();
		}
		
		return collection.stream()
				.filter(Objects::nonNull).sorted(comparing).collect(Collectors.toList());
	}
	
	/**
	 * 
	 * @Description:     将collection转换为类型不变的map
	 * @param <V>        collection的泛型 
	 * @param <K>        map中的key类型
	 * @param collection 需要转换的集合
	 * @param key        v类型转化为k类型的lambda方法
	 * @return Map<K,V> 
	 * @throws：异常描述
	 *
	 */
	public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
		if (CollUtil.isEmpty(collection)) {
			return MapUtil.newHashMap();
		}
		
		return collection.stream().filter(Objects::nonNull).collect(Collectors.toMap(key, Function.identity(),  (l, r) -> l));
	}
	
	/**
	 * 
	 * @Description:     将Collection转化为map(value类型与collection的泛型不同)
     * @param <E>        collection中的泛型
     * @param <K>        map中的key类型
     * @param <V>        map中的value类型
	 * @param collection 需要转化的集合
	 * @param key        E类型转化为K类型的lambda方法
	 * @param value      E类型转化为V类型的lambda方法
	 * @return Map<K,V>  转化后的map
	 * @throws：异常描述
	 *
	 */
    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
        if (CollUtil.isEmpty(collection)) {
            return MapUtil.newHashMap();
        }
        return collection.stream().filter(Objects::nonNull).collect(Collectors.toMap(key, value, (l, r) -> l));
    }
    
    /**
     * 
     * @Description: 			将collection按照规则分类成map，例如：collection<E> ---> Map<K, List<E>>
     * @param <E> 				collection 中的泛型
     * @param <K> 				map中的key类型
     * @param collection 		需要分类的集合
     * @param key 				分类的规则
     * @return Map<K,List<E>>   分类的map
     * @throws：异常描述
     *
     */
    public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
		if (CollUtil.isEmpty(collection)) {
			return MapUtil.newHashMap();
		}
		
		return collection.stream()
				.filter(Objects::nonNull)
				.collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
	}
    
    /**
     * 
     * @Description: 	 将collection转换为List集合
     * @param <E> 		 collection中的泛型
     * @param <T> 		 List中的泛型
     * @param collection 需要转换的集合
     * @param function 	 collection中的泛型转化为list泛型的lambda表达式
     * @return List<T>   转换后的list
     * @throws：异常描述
     *
     */
    public static <E, T> List<T> mapToList(Collection<E> collection, Function<E, T> function) {
		if (CollUtil.isEmpty(collection)) {
			return CollUtil.newArrayList();
		}
		return collection.stream()
				.map(function)
				.filter(Objects::nonNull)
				.collect(Collectors.toList());
	}
    
    /**
     * 
     * @Description:      	collection转化为Set集合，但是两者的泛型不同
     * @param <E> 			collection中的泛型
     * @param <T> 			Set中的泛型
     * @param collection 	需要转化的集合
     * @param function 		collection中的泛型转化为set泛型的lambda表达式
     * @return Set<T> 		转换的set
     * @throws：异常描述
     *
     */
    public static <E, T> Set<T> mapToSet(Collection<E> collection, Function<E, T> function) {
        if (CollUtil.isEmpty(collection) || function == null) {
            return CollUtil.newHashSet();
        }
        return collection
            .stream()
            .map(function)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
	}
    
    /**
     * 
     * @Description:    合并两个相同key类型的map
     * @param <K>       map中的key类型
     * @param <X>       第一个 map的value类型
     * @param <Y>       第二个 map的value类型
     * @param <V>       最终map的value类型
     * @param map1      第一个需要合并的map
     * @param map2		第二个需要合并的map
     * @param merge     合并的lambda，将key  value1 value2合并成最终的类型,注意value可能为空的情况
     * @return Map<K,V> 合并的map
     * @throws：异常描述
     *
     */
    public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) {
		if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) {
			return MapUtil.newHashMap();
		} else if (MapUtil.isEmpty(map1)) {
			map1 = MapUtil.newHashMap();
		} else if (MapUtil.isEmpty(map2)) {
			map2 = MapUtil.newHashMap();
		}
		
		Set<K> key = new HashSet<>();
		key.addAll(map1.keySet());
		key.addAll(map2.keySet());
		Map<K, V> map = new HashMap<>();
		for (K t : key) {
			X x = map1.get(t);
			Y y = map2.get(t);
			V z = merge.apply(x, y);
			if (z != null) {
				map.put(t, z);
			}
		}
		return map;
	}
    
}
